﻿using System;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Web.Http;

namespace Sustainalytics.OAuth.Services.Common
{
    public class ClaimsAuthorize : AuthorizeAttribute
    {
        private string _claimType;
        private string _claimValue;
        private string _denyValue;

        public ClaimsAuthorize(string claimType, string claimValue)
        {
            _claimType = claimType;
            _claimValue = claimValue;
            var rights = claimValue.Split('.');
            var denyRight = new StringBuilder("deny");
            for (int i = 1; i < rights.Length; i++)
            {
                denyRight.AppendFormat(".{0}", rights[i]);
            }
            _denyValue = denyRight.ToString();
        }

        protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            var owinContext = actionContext.Request.GetOwinContext();
            if (owinContext == null)
                throw new Exception("No OWIN context found.");
            var claimsPrincipal = actionContext.Request.GetOwinContext().Authentication.User;
            if (claimsPrincipal == null || !claimsPrincipal.Identity.IsAuthenticated)
                return false;
            var adminClaimFound = claimsPrincipal.Claims.Any(c => c.Type.ToLowerInvariant() == _claimType.ToLowerInvariant() &&
                                                                 c.Value.ToLowerInvariant() == "allow.all");
            if (adminClaimFound)
                return true;
            var denyClaimFound = claimsPrincipal.Claims.Any(c => c.Type.ToLowerInvariant() == _claimType.ToLowerInvariant() &&
                                                                 c.Value.ToLowerInvariant() == _denyValue.ToLowerInvariant());
            if (denyClaimFound)
                return false;
            var allowClaimFound = claimsPrincipal.Claims.Any(c => c.Type.ToLowerInvariant() == _claimType.ToLowerInvariant() && 
                                                                  c.Value.ToLowerInvariant() == _claimValue.ToLowerInvariant());
            return allowClaimFound;
        }

    }
}
